﻿using DevExpress.XtraEditors;
using DevExpress.XtraRichEdit.Services;
using HalconDotNet;
using ImageDefine;
using SmartDisplayControl;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ImageToolMatch
{
    public class ImageActionerMatch
    {
        public ImageToolMatch imageToolMatch;

        public HalconDotNet.HShapeModel sharpModel;
        
        public ImageActionerMatch()
        {
            imageToolMatch = new ImageToolMatch();
        }
        public ImageActionerMatch(ImageToolMatch toolBase)
        {
            imageToolMatch = toolBase;
            
            
                try
                {
                    sharpModel = new HalconDotNet.HShapeModel();
                    string strShmFileName = "";
                    DirectoryInfo root = new DirectoryInfo(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/");
                    FileInfo[] files = root.GetFiles();
                    foreach (FileInfo itemFile in files)
                    {
                        if (itemFile.Extension == ".shm")
                        {
                            strShmFileName = itemFile.FullName;
                            break;
                        }
                    }
                    sharpModel.ReadShapeModel(strShmFileName);
                   
 

                }
                catch
                {
                    sharpModel =new HShapeModel();
                   
                }
            
            

        }

        public bool Run(HalconDotNet.HImage imageInput, SmartDisplayControl.SmartDisplayControl disPlayControl)
        {
            bool bResult = false;
            GeneralLib.HiPerfTimer timer = new GeneralLib.HiPerfTimer();
            timer.Start();

            try
            {
                bResult = RunToool(imageInput, disPlayControl, out imageToolMatch.dResultX, out imageToolMatch.dResultY, out imageToolMatch.dResultA, out imageToolMatch.dResultScore);
                //bResult = true;
                imageToolMatch.bResultOK = bResult;
            }
            catch//(Exception ex)
            {
                bResult = false;
                imageToolMatch.bResultOK = false;
            }

            imageToolMatch.dTimeUsed = timer.Duration;
            return bResult;
        }
       

        public bool CreateShapeModel(HImage image, SmartDisplayControl.SmartDisplayControl disWnd)
        {
            try
            {
                HRegion regionModel;

                HObject  ho_ShapeModelImages;
                HObject ho_ShapeModelRegions;

                // Local control variables 

                HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
                HTuple hv_WindowHandle = new HTuple(), hv_AreaModelRegions = new HTuple();
                HTuple hv_RowModelRegions = new HTuple(), hv_ColumnModelRegions = new HTuple();
                HTuple hv_HeightPyramid = new HTuple(), hv_i = new HTuple();
                HTuple hv_NumLevels = new HTuple(), hv_ModelID = new HTuple();
                HTuple hv_MatchResultID = new HTuple(), hv_NumMatchResult = new HTuple();
                // Initialize local and output iconic variables 

                HOperatorSet.GenEmptyObj(out ho_ShapeModelImages);
                HOperatorSet.GenEmptyObj(out ho_ShapeModelRegions);
                if (imageToolMatch.Setting.regionModel == null)
                {
                    return false;
                }
                if (imageToolMatch.Setting.regionIgnore == null)
                {
                    regionModel = imageToolMatch.Setting.regionModel;
                }
                else
                {
                    if (imageToolMatch.Setting.regionIgnore.CountObj() > 0)
                        regionModel = imageToolMatch.Setting.regionModel.Difference(imageToolMatch.Setting.regionIgnore);
                    else
                        regionModel = imageToolMatch.Setting.regionModel;
                }
                int iWidth, iHeight;
                string strType = "";
                image.GetImagePointer1(out strType, out iWidth, out iHeight);
                HalconDotNet.HImage imageProcess = new HImage(strType, iWidth, iHeight);
                HalconDotNet.HImage imageReduce;


                imageProcess = image.CopyImage();
                imageReduce = image.ReduceDomain(regionModel);

                //HOperatorSet.InspectShapeModel(imageReduce, out ho_ShapeModelImages, out ho_ShapeModelRegions, imageToolMatch.Setting.金字塔最高层, imageToolMatch.Setting.ContrastHigh);
                //disWnd.DispObj(ho_ShapeModelRegions, "green");
                HalconDotNet.HShapeModel sharpModelTemp = new HalconDotNet.HShapeModel();
                //sharpModelTemp.SetGenericShapeModelParam("num_levels", imageToolMatch.Setting.NumLevels);
                //sharpModelTemp.SetGenericShapeModelParam("pyramid_level_lowest", imageToolMatch.Setting.金字塔最低层);
                //sharpModelTemp.SetGenericShapeModelParam("pyramid_level_highest", imageToolMatch.Setting.金字塔最高层);
                sharpModelTemp.SetGenericShapeModelParam("iso_scale_min", imageToolMatch.Setting.ScaleMin);
                sharpModelTemp.SetGenericShapeModelParam("iso_scale_max", imageToolMatch.Setting.ScaleMax);
                sharpModelTemp.SetGenericShapeModelParam("angle_start", (new HTuple(imageToolMatch.Setting.AngleStart)).TupleRad());
                sharpModelTemp.SetGenericShapeModelParam("angle_end", (new HTuple(imageToolMatch.Setting.AngleEnd)).TupleRad());
                
                sharpModelTemp.SetGenericShapeModelParam("num_matches", 1);
                sharpModelTemp.TrainGenericShapeModel(imageReduce);

                
                //if (iNumFounds == 1)
                //{
                //    HTuple hHomMat2D = hGenericShapeModelResult.GetGenericShapeModelResult("best", "hom_mat_2d");
                //    HHomMat2D hHomMat2D1 = new HHomMat2D(hHomMat2D);
                //    sharpModelTemp.SetShapeModelMetric(image, hHomMat2D1, "use_polarity");
                //}

                sharpModelTemp.SetGenericShapeModelObject(imageReduce, "high_noise_sample");
                int iMatchCount = 0;
                //sharpModelTemp.SetGenericShapeModelParam("min_contrast", imageToolMatch.Setting.MinContrast);
                HGenericShapeModelResult hGenericShapeModelResult = sharpModelTemp.FindGenericShapeModel(image, out iMatchCount);
                //disWnd.hWindow.ClearWindow();
                //disWnd.ShowImage(imageReduce);
                if (hGenericShapeModelResult != null)
                {
                    if (iMatchCount == 1)
                    {
                        HObject allCoutours = hGenericShapeModelResult.GetGenericShapeModelResultObject("best", "contours");
                        HXLDCont hXLDCont = new HXLDCont(allCoutours);
                        disWnd.DispObj(allCoutours, "green");

                        HTuple RowRef = hGenericShapeModelResult.GetGenericShapeModelResult("all", "row");
                        HTuple ColumnRef = hGenericShapeModelResult.GetGenericShapeModelResult("all", "column");
                        imageToolMatch.Setting.RefRow = RowRef;
                        imageToolMatch.Setting.RefCol = ColumnRef;
                        HalconDotNet.HXLDCont crossXLD = new HalconDotNet.HXLDCont();
                        crossXLD.GenCrossContourXld(RowRef, ColumnRef, 30, 0.0);
                        disWnd.DispObj(crossXLD);


                        
                        #region 写入模板文件
                        if (!Directory.Exists(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/"))
                        {
                            Directory.CreateDirectory(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/");
                        }
                        else
                        {
                            DirectoryInfo root = new DirectoryInfo(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/");
                            FileInfo[] files = root.GetFiles();
                            foreach (FileInfo itemFile in files)
                            {
                                if (itemFile.Extension == ".shm")
                                {
                                    itemFile.Delete();
                                }
                            }
                        }
                        sharpModelTemp.WriteShapeModel(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/" + imageToolMatch.strName + ".shm");
                        #endregion

                        sharpModel = sharpModelTemp;

                    }
                    else
                    {
                        XtraMessageBox.Show("创建模板的时候只能找到一个模板");
                    }
                    
                }

                XtraMessageBox.Show("创建模板成功");

            }
            catch//(Exception ex)
            {
                XtraMessageBox.Show("创建模板失败");
            }
            return false;
        }
        public bool CreateShapeModel(HImage image, SmartDisplayControl.SmartDisplayControl disWnd,HXLDCont hXLDCont)
        {
            try
            {
                
                HalconDotNet.HShapeModel sharpModelTemp = new HalconDotNet.HShapeModel();
                
                sharpModelTemp.SetGenericShapeModelParam("iso_scale_min", imageToolMatch.Setting.ScaleMin);
                sharpModelTemp.SetGenericShapeModelParam("iso_scale_max", imageToolMatch.Setting.ScaleMax);

                sharpModelTemp.TrainGenericShapeModel(hXLDCont);

                HRegion regionModel;
                HObject ho_ShapeModelImages;
                HObject ho_ShapeModelRegions;
                HOperatorSet.GenEmptyObj(out ho_ShapeModelImages);
                HOperatorSet.GenEmptyObj(out ho_ShapeModelRegions);
                regionModel = imageToolMatch.Setting.regionModel;

                //int iWidth, iHeight;
                //string strType = "";
                //image.GetImagePointer1(out strType, out iWidth, out iHeight);
                //HalconDotNet.HImage imageProcess = new HImage(strType, iWidth, iHeight);

                

                //imageProcess = image.CopyImage();
                HalconDotNet.HImage imageReduce;
                imageReduce = image;
                int iNumFounds = 0;
                sharpModelTemp.SetGenericShapeModelParam("num_matches", 1);
                sharpModelTemp.SetGenericShapeModelParam("min_contrast", imageToolMatch.Setting.MinContrast);
                sharpModelTemp.SetGenericShapeModelParam("min_score", imageToolMatch.Setting.MinScore);
                sharpModelTemp.SetGenericShapeModelParam("angle_start", (new HTuple(imageToolMatch.Setting.AngleStart)).TupleRad());
                sharpModelTemp.SetGenericShapeModelParam("angle_end", (new HTuple(imageToolMatch.Setting.AngleEnd)).TupleRad());


                sharpModelTemp.SetGenericShapeModelParam("max_overlap", imageToolMatch.Setting.MaxOverlap);
                sharpModelTemp.SetGenericShapeModelParam("greediness", imageToolMatch.Setting.Greediness);

                HGenericShapeModelResult hGenericShapeModelResult =sharpModelTemp.FindGenericShapeModel(imageReduce, out iNumFounds);
                if (iNumFounds == 1)
                {
                    HTuple hHomMat2D = hGenericShapeModelResult.GetGenericShapeModelResult("best", "hom_mat_2d");
                    HHomMat2D hHomMat2D1 = new HHomMat2D(hHomMat2D);
                    sharpModelTemp.SetShapeModelMetric(image, hHomMat2D1, "use_polarity");

                    HTuple RowRef = hGenericShapeModelResult.GetGenericShapeModelResult("all", "row");
                    HTuple ColumnRef = hGenericShapeModelResult.GetGenericShapeModelResult("all", "column");

                    imageToolMatch.Setting.RefRow = RowRef;
                    imageToolMatch.Setting.RefCol = ColumnRef;
                    HalconDotNet.HXLDCont crossXLD = new HalconDotNet.HXLDCont();
                    crossXLD.GenCrossContourXld(RowRef, ColumnRef, 30, 0.0);
                    disWnd.DispObj(crossXLD);


                }
                else
                {
                    XtraMessageBox.Show("创建模板失败");
                    return false;
                }
                
                sharpModelTemp.SetGenericShapeModelObject(imageReduce, "high_noise_sample");
                
  
                #region 写入模板文件
                if (!Directory.Exists(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/"))
                {
                    Directory.CreateDirectory(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/");
                }
                else
                {
                    DirectoryInfo root = new DirectoryInfo(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/");
                    FileInfo[] files = root.GetFiles();
                    foreach (FileInfo itemFile in files)
                    {
                        if (itemFile.Extension == ".shm")
                        {
                            itemFile.Delete();
                        }
                    }
                }
                sharpModelTemp.WriteShapeModel(imageToolMatch.imageTask.strPath + @"/" + imageToolMatch.imageTask.Name + @"/" + imageToolMatch.strName + @"/" + imageToolMatch.strName + ".shm");
                #endregion

                sharpModel = sharpModelTemp;
                XtraMessageBox.Show("创建模板成功");
            }
            catch//(Exception ex)
            {
                XtraMessageBox.Show("创建模板失败");
                return false;
            }
            return true;
        }
       
        public bool RunToool(HImage image, SmartDisplayControl.SmartDisplayControl disWnd, out double x, out double y, out double dAngle, out double dScore, bool bShowOrgImage = false)
        {
            
            x = 0.0;
            y = 0.0;
            dScore = 0.0;
            dAngle = 0.0;
            imageToolMatch.ImageToolResults = new  List<ImageToolResult>();
            if (image == null || disWnd == null || sharpModel == null)
            {
                return false;
            }
            HTuple Row, Column, Angle, Scale, Score;
            HTuple RowTran, ColumnTran, AngleTran, ScaleTran, ScoreTran;
            HalconDotNet.HRegion regionModel = new HalconDotNet.HRegion((double)(imageToolMatch.Setting.SRow1), (double)(imageToolMatch.Setting.SCol1),
                           (double)(imageToolMatch.Setting.SRow2), (double)(imageToolMatch.Setting.SCol2));

            int iWidth, iHeight;
            string strType = "";
            image.GetImagePointer1(out strType, out iWidth, out iHeight);

            HalconDotNet.HImage imageProcess;
            imageProcess = image.CopyImage();

            HalconDotNet.HImage imageReduce;
            imageReduce = image.ReduceDomain(regionModel);



            int iMatchCount = 0;
            sharpModel.SetGenericShapeModelParam("num_matches", imageToolMatch.Setting.NumMatches);
            sharpModel.SetGenericShapeModelParam("min_contrast", imageToolMatch.Setting.MinContrast);
            sharpModel.SetGenericShapeModelParam("min_score", imageToolMatch.Setting.MinScore);
            sharpModel.SetGenericShapeModelParam("angle_start", (new HTuple(imageToolMatch.Setting.AngleStart)).TupleRad());
            sharpModel.SetGenericShapeModelParam("angle_end", (new HTuple(imageToolMatch.Setting.AngleEnd)).TupleRad());

           
            sharpModel.SetGenericShapeModelParam("max_overlap", imageToolMatch.Setting.MaxOverlap);
            sharpModel.SetGenericShapeModelParam("greediness", imageToolMatch.Setting.Greediness);

            if (imageToolMatch.Setting.金字塔最低层 < 1)
            {
                //imageToolMatch.Setting.金字塔最低层 = 2;

            }
            else
            {
                sharpModel.SetGenericShapeModelParam("pyramid_level_lowest", imageToolMatch.Setting.金字塔最低层);
                sharpModel.SetGenericShapeModelParam("pyramid_level_highest", imageToolMatch.Setting.NumMatches);
            }
            

            //sharpModel.SetGenericShapeModelObject(imageReduce, "high_noise_sample");
            HGenericShapeModelResult hGenericShapeModelResult = sharpModel.FindGenericShapeModel(imageReduce, out iMatchCount);
            if (iMatchCount >= 1) //actionerSettingSelf.sharpModelSetting.NumMatches)
            {
                HObject allCoutours = hGenericShapeModelResult.GetGenericShapeModelResultObject("all", "contours");
                Row=hGenericShapeModelResult.GetGenericShapeModelResult("all", "row");
                Column = hGenericShapeModelResult.GetGenericShapeModelResult("all", "column");
                Angle = hGenericShapeModelResult.GetGenericShapeModelResult("all", "angle");
                Score = hGenericShapeModelResult.GetGenericShapeModelResult("all", "score");
                HalconDotNet.HXLDCont crossXLD1 = new HalconDotNet.HXLDCont();
                crossXLD1.GenCrossContourXld(Row, Column, 40, Angle);

                #region 转换偏移
                HalconDotNet.HHomMat2D HomMat2DIdentity = new HalconDotNet.HHomMat2D();
                HomMat2DIdentity.HomMat2dIdentity();
                HalconDotNet.HHomMat2D HomMat2DTranslate = HomMat2DIdentity.HomMat2dTranslate(Row[0].D, Column[0].D);
                HalconDotNet.HHomMat2D HomMat2DRotate = HomMat2DTranslate.HomMat2dRotate(Angle[0].D, Row[0].D, Column[0].D);

                HalconDotNet.HXLDCont crossXLD = new HalconDotNet.HXLDCont();
                crossXLD.GenCrossContourXld(imageToolMatch.Setting.MarkerYOffSet, imageToolMatch.Setting.MarkerXOffSet, 80, 0.0);
                HalconDotNet.HXLDCont crossTrans = HomMat2DRotate.AffineTransContourXld(crossXLD);
                HomMat2DRotate.AffineTransPixel(imageToolMatch.Setting.MarkerYOffSet, imageToolMatch.Setting.MarkerXOffSet, out y, out x);

                HalconDotNet.HXLDCont crossXLDTranferAll=new HXLDCont();
                crossXLDTranferAll.GenEmptyObj();
               
                for (int i = 0; i < iMatchCount; i++)
                {
                    HomMat2DIdentity.HomMat2dIdentity();
                    HomMat2DTranslate = HomMat2DIdentity.HomMat2dTranslate(Row[i].D, Column[i].D);
                    HomMat2DRotate = HomMat2DTranslate.HomMat2dRotate(Angle[i].D, Row[i].D, Column[i].D);
                    HalconDotNet.HXLDCont crossXLDTemp = new HalconDotNet.HXLDCont();
                    crossXLDTemp.GenCrossContourXld(imageToolMatch.Setting.MarkerYOffSet, imageToolMatch.Setting.MarkerXOffSet, 40,0);
                    HalconDotNet.HXLDCont crossTransTemp = HomMat2DRotate.AffineTransContourXld(crossXLDTemp);
                    crossXLDTranferAll=crossXLDTranferAll.ConcatObj(crossTransTemp);
                    HTuple hTupleTempRow, hTupleTempCol;
                    HomMat2DRotate.AffineTransPixel(imageToolMatch.Setting.MarkerYOffSet, imageToolMatch.Setting.MarkerXOffSet, out hTupleTempRow, out hTupleTempCol);
                    ImageToolResult newResultItem=new ImageToolResult();
                    newResultItem.Result = true;
                    newResultItem.ResultX = hTupleTempCol.D;
                    newResultItem.ResultY = hTupleTempRow.D;
                    newResultItem.ResultA = HuToAngle(Angle[i].D);
                    newResultItem.ResultScore = Score[i].D;
                    imageToolMatch.ImageToolResults.Add(newResultItem);

                }

                imageToolMatch.dMatchX = Column;
                imageToolMatch.dMatchY = Row;
                imageToolMatch.dMatchA = Angle;

                
                
                #endregion
                dAngle = HuToAngle(Angle.D);
                //让角度变成+/-180度
                double dAngleTemp = dAngle;
                int iAngleTemp = (int)(dAngleTemp * 1000.0);
                iAngleTemp = iAngleTemp % 360000;
                dAngleTemp = (double)iAngleTemp / 1000.0;
                if (dAngleTemp > 180)
                {
                    dAngle = dAngleTemp - 360.0;
                }
                else
                {
                    if (dAngleTemp < -180)
                    {
                        dAngle = dAngleTemp + 360.0;
                    }
                    else
                    {
                        dAngle = dAngleTemp;
                    }
                }

                dScore = Score.D;

               

                if (imageToolMatch.Setting.ShowModule)
                {
                    disWnd.DispObj(allCoutours, "blue");
                }
                if (imageToolMatch.Setting.ShowCross)
                {
                    //disWnd.DispObj(crossXLD1, "red");
                    //disWnd.DispObj(crossTrans, "green");
                    disWnd.DispObj(crossXLDTranferAll, "green");
                }
                
                return true;
            }
            else
            {
                return false;
            }

        }
        private double HuToAngle(double dHu)
        {
            return dHu / Math.PI * 180.0;
        }
        private double AngleToHu(double dAngle)
        {
            return dAngle / 180.0 * Math.PI;
        }

    }
}
